﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DJY.Code.Net
{
    public static  class ZcyRequest
    {
        ///// <summary>
        ///// 获取政采云分类
        ///// </summary>
        //public const string ZCY_API_GETCATEGORY = "/open/zcy.category.get";
        ///// <summary>
        ///// 获取政采云分类属性
        ///// </summary>
        //public const string ZCY_API_GETCATEGORYATTRS = "/open/zcy.category.attrs.get";
        ///// <summary>
        ///// 获取仓库
        ///// </summary>
        //public const string ZCY_API_GETWAREHOUSE = "/open/zcy.item.warehouse.search";
        ///// <summary>
        ///// 添加商品
        ///// </summary>
        //public const string ZCY_API_ADDITEM = "/open/zcy.item.add";
        ///// <summary>
        ///// 修改商品
        ///// </summary>
        //public const string ZCY_API_UPDATEITEM = "/open/zcy.item.update.bycode";
        ///// <summary>
        ///// 更新商品状态
        ///// </summary>
        //public const string ZCY_API_UPDATEITEMSTATUS = "/open/zcy.item.update.listing";
        ////获取图片上传凭证
        //public const string ZCY_API_GETPHOTOOSSTOKEN = "/open/zcy.zoss.filetoken.get";
        ////更新库存
        //public const string ZCY_API_ITEMSTOCKUPDATE = "/open/zcy.item.stock.update";
        ////订单检索
        //public const string ZCY_API_ORDERQUERY = "/open/zcy.order.search";
        ////订单详情
        //public const string ZCY_API_ORDERDETAIL = "/open/zcy.order.get";
        ////const string ZCY_API_ORDERDETAIL = "/test/order.query.byid";
        ////接收订单
        //public const string ZCY_API_ACCEPTORDER = "/open/zcy.order.accept";
        ////刷新商品状态
        //public const string ZCY_API_DISTRICT = "/open/zcy.item.district.get";
        /// <summary>
        /// 请求超时时间
        /// </summary>
        const int REQUEST_TIMEOUT = 30000;

        /// <summary>
        /// 执行请求
        /// </summary>
        /// <param name="server">服务器地址</param>
        /// <param name="api">API</param>
        /// <param name="method">POST,GET</param>
        /// <param name="paras">参数</param>
        /// <returns></returns>
        public static string Request(string server,
            string api,
            string appKey,
            string appSecret,
            string method,
            Dictionary<string, object> paras)
        {

            if (string.IsNullOrEmpty(method))
            {
                method = "GET";
            }
            method = method.ToUpper();

            Dictionary<string, string> headers = new Dictionary<string, string>();
            headers.Add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
            headers.Add("Accept", "application/json");
            headers.Add("X-Ca-Key", appKey);
            headers.Add("X-Ca-Format", "json2");

            if (!api.StartsWith("/"))
            {
                api = "/" + api;
            }

            Dictionary<string, object> bodyMap = null;
            string uri = api;

            if (method.Equals("GET"))
            {
                if (paras != null && paras.Count > 0)
                {
                    if (uri.IndexOf("?") > 0)
                    {
                        uri += "&";
                    }
                    else
                    {
                        uri += "?";
                    }
                    uri += string.Join("&", (from kv in paras
                                             select string.Format("{0}={1}", kv.Key,
                                             System.Web.HttpUtility.UrlEncode(string.Format("{0}", kv.Value)))).ToArray());
                }
            }
            else
            {
                if (paras == null)
                {
                    paras = new Dictionary<string, object>();
                }

                string data = Newtonsoft.Json.JsonConvert.SerializeObject(paras);
                //POST
                bodyMap = new Dictionary<string, object>();
                bodyMap.Add("_data_", data);
                
            }

            string stringToSign = Zcy_Sign.buildStringToSign(uri, headers, bodyMap, method.ToUpper());

            //通过HmacSHA256以及base64加密生成签名
            byte[] p = Encoding.UTF8.GetBytes(appSecret);
            byte[] s = Encoding.UTF8.GetBytes(stringToSign);
            HMACSHA256 Sha256 = new HMACSHA256(p);
            byte[] Result = Sha256.ComputeHash(s);//source
            string signature = Convert.ToBase64String(Result);

            /*将签名设置到header中*/
            headers.Add("X-Ca-Signature", signature);

            server = server.TrimEnd('/');

            return SendRequest(server + uri, method, headers, bodyMap);
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="method"></param>
        /// <param name="header"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private static string SendRequest(string url,
            string method,
            Dictionary<string, string> header,
            Dictionary<string, object> parameters)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }

            HttpWebRequest request = null;
            //string baseUrl = "http://api.zcygov.cn";
            request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            request.Timeout = REQUEST_TIMEOUT;

            request.Headers.Add("X-Ca-Format", header["X-Ca-Format"]);
            request.Headers.Add("X-Ca-Key", header["X-Ca-Key"]);
            request.Headers.Add("X-Ca-Signature-Headers", header["X-Ca-Signature-Headers"]);
            request.Headers.Add("X-Ca-Signature", header["X-Ca-Signature"]);

            request.ContentType = header["Content-Type"];
            request.Accept = header["Accept"];

            request.CookieContainer = new CookieContainer();

            //如果需要POST数据  
            if (parameters != null && parameters.Count > 0)
            {
                string para = string.Join("&", (from kv in parameters
                                                select string.Format("{0}={1}", kv.Key,
                                                System.Web.HttpUtility.UrlEncode(string.Format("{0}", parameters[kv.Key])))).ToArray());

                byte[] data = Encoding.UTF8.GetBytes(para.ToString());
                request.GetRequestStream().Write(data, 0, data.Length);
            }

            using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()))
            {
                return reader.ReadToEnd();
            }
        }

        public class DATA_RESPONSE
        {
            public OSSTOKEN data_response { get; set; }
        }

        public class OSSTOKEN
        {
            public string success { get; set; }
            public OSSRESULT result { get; set; }
        }

        public class OSSRESULT
        {
            public string securityToken { get; set; }
            public string accessKeySecret { get; set; }
            public string accessKeyId { get; set; }
            public string expiration { get; set; }
            public string bucket { get; set; }
            public System.Collections.ArrayList data { get; set; }
            public string endPoint { get; set; }
        }
    }
}
